#pragma once
#include "ZuiLib.h"
#include "LRefObject.h"

namespace ZuiLib
{

class LSchedulerImpl :public ZSchedulerBase
{
public:
	ZUI_CLASS_NAME("zui.Scheduler");

	LSchedulerImpl():m_callId(0){}

	LSchedulerImpl(LuaObject func)
	{
		m_callId = saveCallbackFunction(func);
	}

	~LSchedulerImpl() {
		LuaState* L = ZScriptEngine::Instance()->GetLuaState();
		if(L)
			removeCallbackFunction(L, m_callId);
	}

	void OnSchedule(Uint32 tick)
	{
		LuaState* L = ZScriptEngine::Instance()->GetLuaState();
		try {
			LuaFunction func = getCallbackFunction(L, m_callId);
			if (func.isValid())
			{
				func();
			}
		}
		catch (LuaException e)
		{
			LOG(LS_LUAERROR) << e.what();
		}
	}


	void Schedule(Uint32 delay, Uint32 interval, Uint32 repeat)
	{
		ZuiLib::ZScheduler::Instance()->Schedule(this,
			schedule_selector(ZuiLib::LSchedulerImpl::OnSchedule), delay, interval, repeat);
	}

	void Unschedule()
	{
		ZuiLib::ZScheduler::Instance()->Unschedule(this, 
			schedule_selector(ZuiLib::LSchedulerImpl::OnSchedule));
	}
private:
	int m_callId;
};


class LScheduler :public LRefObject<ZuiLib::LSchedulerImpl>
{
public:
	void ctor(LuaFuncState& L)
	{
		pThis = new ZRefCountedObject<LSchedulerImpl>(L.arg(0));
		pThis->AddRef();
	}

	int schedule(LuaFuncState& L)
	{
		Uint32 delay = L.arg(0).toUInt();
		Uint32 interval = L.arg(1).toUInt();

		Uint32 repeat = kForever;
		if(L.arg(2).isNumber())
			repeat = L.arg(2).toUInt();
		pThis->Schedule(delay, interval, repeat);
		return 0;
	}

	int unschedule(LuaFuncState& L)
	{
		pThis->Unschedule();
		return 0;
	}

	BEGIN_MAP_FUNC(LScheduler)
	DECLARE_FUNC(schedule),
	DECLARE_FUNC(unschedule),
	END_MAP_FUNC
};

}//namespace
